package com.managertrade.util.strategy;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import okhttp3.*;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class LighterClient {
    private static ObjectMapper mapper = new ObjectMapper();
    private static final String BASE_URL = "https://mainnet.zklighter.elliot.ai/api/v1";
    private static final String API_KEY_PRIVATE_KEY = "2bfc0a67a3b8fe9c9c838bf7ae16875b338a9d2e40df9002cf9eca6f587193832fe17093484d8526";
    private static final int ACCOUNT_INDEX = 242955; // 账户索引（根据你生成的 key）
    private static final int API_KEY_INDEX = 0;
    private static final String PROXY_HOST = "127.0.0.1";
    private static final int PROXY_PORT = 22307; // 本地代理端口
    private static final OkHttpClient client;
    static {
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT));
        client = new OkHttpClient.Builder()
                .proxy(proxy)
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build();
    }
    /** ==================== 内部类封装 ==================== */
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class AccountResponse {
        public int code;
        public int total;
        public List<Account> accounts;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Account {
        public int code;
        public int account_type;
        public int index;
        public String l1_address;
        public String available_balance;
        public String collateral;
        public int account_index;
        public String total_asset_value;
        public String cross_asset_value;
        public List<Position> positions;
        // 其他字段可以根据需要增加
    }
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Position {
        public int market_id;
        public String symbol;
        public String initial_margin_fraction;
        public int open_order_count;
        public int pending_order_count;
        public int position_tied_order_count;
        public int sign;
        public String position;
        public String avg_entry_price;
        public String position_value;
        public String unrealized_pnl;
        public String realized_pnl;
        public String liquidation_price;
        public int margin_mode;
        public String allocated_margin;
    }
    private final Gson gson = new Gson();

    /** ==================== 公共方法 ==================== */

    // 获取 nonce
    public long getNextNonce() throws Exception {
        String url = BASE_URL + "/nextNonce?api_key_index=" + API_KEY_INDEX+"&account_index="+ ACCOUNT_INDEX;
        Request request = new Request.Builder().url(url).build();
        try (Response response = client.newCall(request).execute()) {
            String body = response.body().string();
            System.out.println("getNextNonce HTTP code: " + response.code());
            System.out.println("getNextNonce body: " + body);

            if (!response.isSuccessful()) {
                throw new RuntimeException("获取 nonce 失败, HTTP code=" + response.code());
            }

            Map<String, Object> res = gson.fromJson(body, Map.class);
            Object nonceObj = res.get("nonce");
            if (nonceObj == null) {
                throw new RuntimeException("返回内容中没有 next_nonce 字段");
            }
            return ((Number) nonceObj).longValue();
        }
    }

    // Ed25519 签名函数
    private String signEd25519(String message) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(API_KEY_PRIVATE_KEY);
        Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters(privateKeyBytes, 0);
        Ed25519Signer signer = new Ed25519Signer();
        signer.init(true, privateKey);
        signer.update(message.getBytes(), 0, message.getBytes().length);
        byte[] signature = signer.generateSignature();
        return Base64.getEncoder().encodeToString(signature);
    }

    // 发送交易
    private String sendTx(String txType, String txInfoJson, String signature, int accountIndex, int apiKeyIndex) throws Exception {
        String url = BASE_URL + "/sendTx";

        RequestBody body = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("tx_type", txType)
                .addFormDataPart("tx_info", txInfoJson)
                .addFormDataPart("price_protection", "true")
                .addFormDataPart("signature", signature)
                .build();

        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .addHeader("accept", "application/json")
                .build();

        try (Response resp = client.newCall(request).execute()) {
            String respBody = resp.body().string();
            System.out.println("sendTx HTTP code: " + resp.code());
            System.out.println("sendTx body: " + respBody);
            return respBody;
        }
    }

    /** ==================== 功能封装 ==================== */

    // 下单（LIMIT）
    public String createOrder(String market, String side, double price, double amount) throws Exception {
        long nonce = getNextNonce();

        // 构建 tx_info Map
        Map<String, Object> txInfoMap = new LinkedHashMap<>();
        txInfoMap.put("market", market);
        txInfoMap.put("side", side); // "BUY" 或 "SELL"
        txInfoMap.put("price", (long)(price * 1_000_000)); // 转整数
        txInfoMap.put("base_amount", (long)(amount * 1_000_000));
        txInfoMap.put("order_type", "ORDER_TYPE_LIMIT");
        txInfoMap.put("time_in_force", "ORDER_TIME_IN_FORCE_GOOD_TILL_TIME");
        txInfoMap.put("client_order_index", System.currentTimeMillis());
        txInfoMap.put("reduce_only", false);
        txInfoMap.put("post_only", false);

        // tx_info 必须是 JSON 字符串
        String txInfoJson = mapper.writeValueAsString(txInfoMap);

        // 构建顶层交易 JSON
        Map<String, Object> txBody = new LinkedHashMap<>();
        txBody.put("account_index", ACCOUNT_INDEX);
        txBody.put("api_key_index", API_KEY_INDEX);
        txBody.put("nonce", nonce);
        txBody.put("tx_type", 14); // 下单类型
        txBody.put("tx_info", txInfoJson);
        txBody.put("price_protection", true);

        // 签名整个 JSON
        String signature = signEd25519(mapper.writeValueAsString(txBody));

        // 发送请求
        return sendTx(
                String.valueOf(14),
                txInfoJson,
                signature,
                ACCOUNT_INDEX,
                API_KEY_INDEX
        );
    }

    // 撤单


    // 查询所有订单
    public String listOrders() throws Exception {
        String url = BASE_URL + "/orders";
        Request request = new Request.Builder().url(url).build();
        try (Response resp = client.newCall(request).execute()) {
            String body = resp.body().string();
            System.out.println("listOrders HTTP code: " + resp.code());
            System.out.println("listOrders body: " + body);
            return body;
        }
    }

    // 查询持仓
    // 查询持仓（修正）
    // 查询持仓（修正）
    public AccountResponse  getPositions() throws Exception {
        // by=index，value=你的账户索引
        HttpUrl url = HttpUrl.parse(BASE_URL + "/account").newBuilder()
                .addQueryParameter("by", "index")
                .addQueryParameter("value", String.valueOf(ACCOUNT_INDEX))
                .build();

        Request request = new Request.Builder()
                .url(url)
                .addHeader("Content-Type", "application/json")
                .build();

        try (Response resp = client.newCall(request).execute()) {
            String body = resp.body().string();

            if (!resp.isSuccessful()) {
                throw new RuntimeException("获取持仓失败, HTTP code=" + resp.code());
            }

            AccountResponse accountResponse = mapper.readValue(body, new TypeReference<AccountResponse>() {
            });
            return accountResponse;
        }
    }


    /** ==================== 测试入口 ==================== */
    public static void main(String[] args) throws Exception {
        LighterClient lighter = new LighterClient();

        System.out.println("=== 查询持仓 ===");
        AccountResponse positions = lighter.getPositions();

        System.out.println("=== 下单 ===");
        String result = lighter.createOrder("ETH-USDC", "BUY", 2500.0, 0.05);
        System.out.println(result);

        System.out.println("=== 查询订单 ===");
        System.out.println(lighter.listOrders());
    }
}
